using System;
using System.Collections.Generic;

namespace foundation
{
    public class ClassPool
    {
        private readonly Type _type;
        private readonly List<object> _list = new List<object>();
        public int MaxCount = 10000;

        public ClassPool(Type type)
        {
            _type = type;
        }

        public object Get()
        {
            object value;
            if (_list.Count > 0)
            {
                value = _list[_list.Count - 1];
                _list.RemoveAt(_list.Count - 1);
            }
            else
            {
                value = Activator.CreateInstance(_type);
            }


            return value;
        }

        public bool Set(object value)
        {
            if (_list.Count > MaxCount) return false;
            if (_list.Contains(value)) return false;
            _list.Add(value);
            return true;
        }
    }


    public static class ClassUtils
    {
        private static readonly Dictionary<Type, object> Instances = new Dictionary<Type, object>();
        private static readonly Dictionary<Type, ClassPool> Pools = new Dictionary<Type, ClassPool>();


        public static T Instance<T>(Type type = null)
        {
            if (null == type) type = typeof(T);
            object instance;
            if (Instances.ContainsKey(type))
            {
                instance = Instances[type];
            }
            else
            {
                instance = Activator.CreateInstance(type);
                Instances[type] = instance;
            }

            return (T)instance;
        }

        public static object Instance(Type type){
            object instance;
            if (Instances.ContainsKey(type))
            {
                instance = Instances[type];
            }
            else
            {
                instance = Activator.CreateInstance(type);
                Instances[type] = instance;
            }

            return instance;
        }

        public static T PoolGet<T>()
        {
            var type = typeof(T);
            ClassPool pool;

            if (Pools.ContainsKey(type))
            {
                pool = Pools[type];
            }
            else
            {
                pool = new ClassPool(type);
                Pools[type] = pool;
            }

            return (T)pool.Get();
        }


        public static bool PoolSet(object value)
        {
            var type = value.GetType();
            if (!Pools.ContainsKey(type)) return false;
            var pool = Pools[type];
            var boolean = false;
            if (null != pool)
            {
                RecycleAttribute.recycle(value);
                type.GetMethod("onRecycle")?.Invoke(value, new object[] { });
                boolean = pool.Set(value);
            }
            return boolean;


        }
    }



}